perm filename MTADDT.SAI[SS,SYS] blob
sn#684191 filedate 1980-05-05 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00009 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 BEGIN "MTADDT"
C00003 00003 ! MTC bit assignments and CONO procedures
C00007 00004 ! MTS bit assignments and procedures
C00009 00005 ! MTM bit assignments and procedures
C00012 00006 ! Low level CONO, DATAO, CONI, DATAI routines
C00017 00007 ! User interface routines: prompt, GetCmd
C00020 00008 ! Execute a command string
C00027 00009 ! The main loop
C00029 ENDMK
C⊗;
BEGIN "MTADDT"
REQUIRE "HEADER.SAI[LIB,ROB]" SOURCE_FILE;
DEFINE Bit(arg) = {(1 LSH (35-arg))};
DEFINE
promptstr = {"*"},
againchr = {"*"};
RECORD_CLASS cmd(
STRING cmdstr;
STRING oldstr;
INTEGER rptarg);
INTEGER MTCStickyBits, Sleeptics;
! MTC bit assignments and CONO procedures;
DEFINE MTC = {'220}; comment MTC is device 220;
! Next are the CONI/CONO bit assignments. The non-indented definitions
are the bit position in the 36-bit word. The sub-categories following
are the meaning of the bits in those positions;
DEFINE
RDFER = {Bit(18)}, comment False End of Record (CONI only);
WTEWC = {Bit(19)}, comment Write Clock Enable (CONI only);
SLICE = {Bit(20)}, comment Slice Level;
SLICHI = {0}, comment Set high slice (normal);
SLICLO = {1}, comment set low slice;
PARITY = {Bit(21)}, comment Parity;
PAREVN = {00}, comment set even parity;
PARODD = {01}, comment set odd parity;
DENSITY = {Bit(23)}, comment Density (2 bits wide);
BPI200 = {00}, comment 200 BPI;
BPI556 = {01}, comment 556 BPI;
BPI800 = {02}, comment 800 BPI;
MTCFUNC = {Bit(27)}, comment function code (4 bits wide);
MTCNOP = {'00}, comment NO OPERATION;
MTCREW = {'01}, comment REWIND;
MTCWRT = {'02}, comment WRITE;
MTCWEF = {'03}, comment WRITE END-OF-FILE;
MTCRDC = {'04}, comment READ-COMPARE (NOT USED);
MTCRED = {'05}, comment READ;
MTCSFR = {'06}, comment SPACE FORWARD RECORD;
MTCBSP = {'07}, comment BACKSPACE RECORD;
MTCZZZ = {'10}, comment NO OPERATION (NOT USED);
MTCRAU = {'11}, comment REWIND AND UNLOAD (SAME AS REWIND AT STANFORD);
MTCRAR = {'12}, comment READ ACROSS RECORD (NOT USED);
MTCW3I = {'13}, comment WRITE THREE INCHES (APPROX) OF MAG TAPE;
MTCWLE = {'14}, comment WRITE WITH LONG EOR (NOT USED);
MTCRDB = {'15}, comment READ BACKWARD (NOT USED);
MTCSFF = {'16}, comment SPACE FORWARD FILE;
MTCBSF = {'17}, comment BACKSPACE FILE;
POOL = {Bit(28)}, comment Hold (don't pool) after completion;
UNITNUM = {Bit(31)}, comment Software Unit number (3 bits wise);
EORDISABLE = {Bit(32)}, comment maintenance only;
MTCPIA = {Bit(35)}, comment PIA assignment (3 bits wide);
PIAOFF = {'0}, comment Turn off the PIA;
PIAON = {'4}; comment Turn on the PIA;
! MTS bit assignments and procedures;
COMMENT ⊗
Device 224 MTS
Bit CONO CONI
18 INT CLR CS ILC Initial-Clear / Illegal command
19 unused MD DCS Motion Stop delay in progress
20 LIE MD LIF Load point interrupt Enable/Bit
21 XNE CS XNC Transfer next command Enable/Bit
22 T Rewinding
23 T End Point
24 T Load Point
25 TLR Last Last operation was a Write
26 TFR A/B work Local ∨ other controller is using this unit
27 EFF End of File Flag
28 T Write Lock
29 RD MIS Missed character
30 RD RCE Read compare error
31 RD LPE Long. Parity Error
32 PER Lat. Parity Error
33 EFE MD ERF End of Record Flag Enable/Bit
34 Prog JNU ST Ready Tape Unit Ready
35 ICE MD ICR Interface & Control Enable/Ready
⊗;
DEFINE MTS = {'224}; comment MTS is device 224;
DEFINE
MTSCLR = {Bit(18)};
! MTM bit assignments and procedures;
COMMENT ⊗
Device 230 MTM
Note: All CONO bit are ignored, however the CONO itself causes a programmed
CHP pulse to occur.
Bit CONI
18 CS UPS Up to speed
19 CS RIP Record in Progress
20 CS ERM End of record motion delay in progress
21 CS CON Motion Continue Selected
22 CS CHF Command Hold buffer Full
23 CS UNS Unit selected new command
24 CM Function-8 Final function register
25 CM Function-4
26 CM Function-2
27 CM Function-1
28 CM Unit-4 Final Unit register
29 CM Unit-2
30 CM Unit-1
31 MD MOD
32 RD FCD
33 RD ERD Read End of Record delay
34 RD MCD
35 WT EWD End of record Write delay
⊗;
! Low level CONO, DATAO, CONI, DATAI routines;
! These routines should be in a .REL file library on [LIB,ROB];
DEFINE CONO = {'700200000000};
DEFINE CONI = {'700240000000};
DEFINE DATAO = {'700140000000};
DEFINE DATAI = {'700040000000};
DEFINE EIOTM = {'047000400005};
DEFINE POINTC(bytsiz,addr,lowbit) = {((bytsiz LSH 24)+((35-lowbit) LSH 30)+addr)};
PROCEDURE ConoDev(
INTEGER dev,conoword);
Q⊂ "ConoDev"
LABEL $liotm;
! This obtuse bit of start code fabricates a CONO instruction in AC 2,
depositing the device code and cono data word in the proper fields.
It then enters IOT user mode, XCTs the CONO, and gets out of IOT user
mode;
MOVE 2,[CONO]; ! start with a naked CONO
! ac2 now = CONO nil,0;
MOVE 1,dev;
LSH 1,-2; ! The device code is really only 7 bits wide (not 9);
DPB 1,[POINTC(7,2,9)]; ! deposit the device code;
! ac2 now = CONO DEV,0;
MOVE 1,conoword;
DPB 1,[POINTC(18,2,35)];! deposit the data;
! ac2 now = CONO DEV,CONOWORD;
EIOTM; ! enter the dangerous land...;
XCT 2; ! do the instruction;
! the next two instructions get us out of IOT user mode by
! turning off the PC flags. I would have said JRST 2,@[.+1],
! but the silly SAIL assembler doesnt do address arithmetic;
MOVEI 3,$liotm;
JRST 2,@3;
$liotm:
⊃ "ConoDev";
INTEGER PROCEDURE ConiDev(
INTEGER dev);
Q⊂ "ConiDev"
LABEL $liotm;
MOVE 2,[CONI]; ! CONI nil,0;
MOVE 1,dev;
LSH 1,-2; ! The device code is really only 7 bits wide (not 9);
DPB 1,[POINTC(7,2,9)]; ! CONI DEV,0;
HRRI 2,1; ! CONI DEV,1 ie, return results in AC 1;
EIOTM; ! enter the dangerous land...;
XCT 2; ! do the instruction;
MOVEI 3,$liotm; ! Get out of IOT user mode (the hard way);
JRST 2,@3;
$liotm:
⊃ "ConiDev";
PROCEDURE DataoDev(
INTEGER dev,dataoword);
Q⊂ "DataoDev"
LABEL $liotm;
MOVE 2,[DATAO]; ! DATAO nil,0;
MOVE 1,dev;
LSH 1,-2; ! The device code is really only 7 bits wide (not 9);
DPB 1,[POINTC(7,2,9)]; ! DATAO DEV,0;
HRRI 2,1; ! DATAO DEV,1 ie, AC 1 will have the data;
MOVE 1,dataoword; ! put the data in AC1
EIOTM; ! enter the dangerous land...;
XCT 2; ! do the instruction;
MOVEI 3,$liotm; ! Get out of IOT user mode;
JRST 2,@3;
$liotm:
⊃ "DataoDev";
INTEGER PROCEDURE DataiDev(
INTEGER dev);
Q⊂ "DataiDev"
LABEL $liotm;
MOVE 2,[DATAI]; ! DATAI nil,0;
MOVE 1,dev;
LSH 1,-2; ! The device code is really only 7 bits wide (not 9);
DPB 1,[POINTC(7,2,9)]; ! DATAI DEV,0;
HRRI 2,1; ! DATAI DEV,1 ie, return results in AC 1;
EIOTM; ! enter the dangerous land...;
XCT 2; ! do the instruction;
MOVEI 3,$liotm; ! Get out of IOT user mode (the hard way);
JRST 2,@3;
$liotm:
⊃ "DataiDev";
! User interface routines: prompt, GetCmd;
PROCEDURE Prompt; ⊂ PRINT(promptstr) ⊃;
! PROCEDURE MakeUpper(INTEGER chr);! RETURN(IF ("a"≤chr≤"z") (chr-("a"-"A")) ELSE chr);
INTEGER PROCEDURE MakeUpper(INTEGER chr);
IF ("a"≤chr≤"z")
THEN RETURN(chr-("a"-"A"))
ELSE RETURN(chr);
PROCEDURE GetCmd(
RECORD_POINTER(cmd) C);
⊂ "GetCmd"
STRING str;
INTEGER brk;
str ← INCHWL;
IF ("0" ≤ str ≤ "9")
THEN
⊂ "Got a numeric argument"
cmd:rptarg[C] ← CVD(str);
WHILE ("0" ≤ str ≤ "9") DO str ← str[2 TO ∞];
⊃ "Got a numeric argument"
ELSE
⊂ "No numeric argument"
cmd:rptarg[C] ← 1; ! no numeric arg defaults to 1;
⊃ "No numeric argument";
IF (str ≠ againchr) THEN cmd:cmdstr[C] ← str;
⊃ "GetCmd";
! Execute a command string;
PROCEDURE Execute(
RECORD_POINTER(cmd) C);
⊂ "Execute"
STRING str;
INTEGER ChrPtr; ! points to current character within string;
str ← cmd:cmdstr[C];
FOR ChrPtr ← 1 THRU LENGTH(str) DO
⊂ "Do a command"
CASE MakeUpper(str[ChrPtr FOR 1]) OF
⊂ "command case"
["?"]
⊂ "list commands"
PRINT("
This is a simple tape drive diagnostic which does direct IO instructions to the
tape controller. At the ",promptstr," prompt, type a string of commands. If you
precede the string with a number, the sequence will be repeated that many times.
For example, ""*99iesss"" will do the sequence initial-clear, write end-of-file,
and sleep for 50 milliseconds 99 times.
Valid commands are:
? type this list (does it only once per loop)
C read-compare
D set the density (does it only once per loop)
E write an end-of-file mark
I execute an initial-clear
N no operation
Q quit and return to the monitor
R read the tape
S sleep for the time specified by last T command
T set number of milliseconds to sleep (to nearest 1/60 second)
W write
← rewind
> space forward record
< backspace record
≥ space forward file
≤ backspace file
∃ write three inches (approx) of mag tape
");
str ← str[1 TO ChrPtr-1] & str[ChrPtr+1 TO ∞]; ! remove from list;
⊃ "list commands";
["C"]
⊂ "rdcompare"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCRDC));
⊃ "rdcompare";
["D"]
⊂ "Set Density"
STRING Dstr; INTEGER brk,Dens;
PRINT("Density (0 for 220, 1 for 550, 2 for 800): ");
Dstr ← INCHWL;
CASE Dens ← INTSCAN(Dstr,brk) OF
⊂ "Density case"
[0] print("Density = 200 bpi.",↓);
[1] print("Density = 550 bpi.",↓);
[2] print("Density = 800 bpi.",↓);
ELSE print("Unknown density specification.",↓)
⊃ "Density case";
IF (0≤Dens≤2) THEN
MTCStickybits ← MTCStickyBits LAND (LNOT 3*DENSITY) + Dens*Density;
str ← str[1 TO ChrPtr-1] & str[ChrPtr+1 TO ∞]; ! remove from list;
⊃ "Set Density";
["E"]
⊂ "Write End-of-File"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCWEF));
⊃ "Write End-of-File";
["I"]
⊂ "Initial-clear"
ConoDev(MTS,MTSCLR);
⊃ "Initial-clear";
["N"]
⊂ "No-op"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCNOP));
⊃ "No-op";
["Q"]
⊂ "Quit"
ConoDev(MTC,MTCPIA * PIAON); comment Restore the PIA;
cmd:rptarg[C] ← 0;
⊃ "Quit";
["R"]
⊂ "Read The Tape Dammit"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCRED));
⊃ "Read The Tape Dammit";
["S"]
⊂ "Sleep"
INTEGER I;
FOR I ← 0 THRU Sleeptics DO
Q⊂ "Sleep for a tic"
DEFINE sleep = {'047000000031};
MOVEI 1,0 ;
SLEEP 1, ;
⊃ "Sleep for a tic";
⊃ "Sleep";
["T"]
⊂ "TimeSet"
STRING Tstr; INTEGER brk, ttics;
PRINT("How many milliseconds per S command: "); Tstr ← INCHWL;
ttics ← (60 * INTSCAN(Tstr,brk))/1000;
IF ttics=0 THEN PRINT("(no change)",↓) ELSE Sleeptics ← ttics;
PRINT("S commands now sleep for ",sleeptics*(1000/60)," milliseconds",↓);
str ← str[1 TO ChrPtr-1] & str[ChrPtr+1 TO ∞]; ! remove from list;
⊃ "TimeSet";
["W"]
⊂ "MTCWRT"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCWRT));
⊃ "MTCWRT";
["←"]
⊂ "rewind"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCREW));
⊃ "rewind";
[">"]
⊂ "MTCSFR"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCSFR));
⊃ "MTCSFR";
["<"]
⊂ "MTCBSP"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCBSP));
⊃ "MTCBSP";
["≥"]
⊂ "MTCSFF"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCSFF));
⊃ "MTCSFF";
["≤"]
⊂ "MTCBSF"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCBSF));
⊃ "MTCBSF";
["∃"]
⊂ "MTCW3I"
ConoDev(MTC,MTCStickyBits+(MTCFUNC * MTCW3I));
⊃ "MTCW3I";
ELSE PRINT("Unrecognized command character ",str[ChrPtr FOR 1],↓)
⊃ "command case"
⊃ "Do a command";
! D$PRINT(<"Command string = ",str,↓>);
cmd:cmdstr[C] ← str; ! update the command string;
⊃ "Execute";
! The main loop;
RECORD_POIJTER(cmd) C;
C ← NEW_RECORD(cmd);
cmd:cmdstr[C] ← "";
cmd:oldstr[C] ← "";
cmd:rptarg[C] ← 0;
SleepTics ← 1; ! Default to 1 tic;
MTBStickyBits ← (PARITY * @ARODD) + (DEJSITY * BPI800) # (MTCPIA * PIAOFF);
! set odd paraty, density at 800bpi, PIA tqrned off;
PRINT("Type ""?"" for help.",↓);
DO
⊂ "main" ! The main coMmand loop;
INTEGER I;
prompt;
GetCmd(C);
IF cmd:rptarg[C] > 0 THEN FOR I ← 1 THRU cmd:rptarg[C] DO Execute(C);
⊃ "main"
UNTIL cmd:rptarg[C] = 0;
print("So long.",↓);
quit;
END "MTADDT";